/**
 * UE5桥接模块单元测试
 */

import { UE5Bridge } from '../../src/ue5/bridge';

// 导入清理函数
const { clearMocks, restorePerformanceNow } = require('../setup');

describe('UE5桥接模块测试', () => {
  let bridge;
  
  // 模拟UE对象
  const mockUE = {
    MicrophoneSDK: {
      OnMicrophoneStatusChanged: jest.fn(),
      OnAudioLevelChanged: jest.fn(),
      OnMicrophoneError: jest.fn(),
      OnAudioDataReceived: jest.fn()
    }
  };
  
  beforeEach(() => {
    // 保存原始的全局UE对象（如果存在）
    global._originalUE = global.UE;
    
    // 设置模拟的UE对象
    global.UE = mockUE;
    
    // 创建桥接实例
    bridge = new UE5Bridge();
  });
  
  afterEach(() => {
    // 清理资源
    if (bridge) {
      bridge.dispose();
      bridge = null;
    }
    
    // 恢复原始的UE对象
    if (global._originalUE !== undefined) {
      global.UE = global._originalUE;
    } else {
      delete global.UE;
    }
    delete global._originalUE;
    
    // 清理模拟
    clearMocks();
  });
  
  afterAll(() => {
    // 恢复原始函数
    restorePerformanceNow();
  });
  
  test('桥接实例化', () => {
    expect(bridge).toBeInstanceOf(UE5Bridge);
  });
  
  test('初始化SDK', async () => {
    const initResult = await bridge._initSDK();
    expect(initResult).toBe(true);
  });
  
  test('调用UE5函数', () => {
    // 测试UE对象存在时的调用
    bridge._callUE5('OnMicrophoneStatusChanged', 'active');
    expect(mockUE.MicrophoneSDK.OnMicrophoneStatusChanged).toHaveBeenCalledWith('active');
    
    // 测试函数不存在时不抛出错误
    expect(() => bridge._callUE5('NonExistentFunction', 'test')).not.toThrow();
  });
  
  test('开始麦克风', async () => {
    const result = await bridge.startMicrophone();
    expect(result).toBe(true);
    expect(mockUE.MicrophoneSDK.OnMicrophoneStatusChanged).toHaveBeenCalledWith('active');
  });
  
  test('停止麦克风', async () => {
    // 先开始麦克风
    await bridge.startMicrophone();
    
    // 然后停止麦克风
    const result = await bridge.stopMicrophone();
    expect(result).toBe(true);
    expect(mockUE.MicrophoneSDK.OnMicrophoneStatusChanged).toHaveBeenCalledWith('inactive');
  });
  
  test('获取麦克风状态', async () => {
    // 初始状态应该是未监听
    expect(bridge.getMicrophoneStatus()).toBe('inactive');
    
    // 开始麦克风后状态应该变为活动
    await bridge.startMicrophone();
    expect(bridge.getMicrophoneStatus()).toBe('active');
    
    // 停止麦克风后状态应该变回未监听
    await bridge.stopMicrophone();
    expect(bridge.getMicrophoneStatus()).toBe('inactive');
  });
  
  test('设置增益', () => {
    const testGain = 0.7;
    expect(() => bridge.setGain(testGain)).not.toThrow();
  });
  
  test('启用调试模式', () => {
    expect(() => bridge.enableDebug(true)).not.toThrow();
    expect(() => bridge.enableDebug(false)).not.toThrow();
  });
  
  test('音频级别变化事件', async () => {
    await bridge._initSDK();
    
    // 模拟音频级别变化事件
    document.dispatchEvent(new CustomEvent('audioLevelChange', { detail: { level: 0.5 } }));
    
    // 验证UE函数被调用
    expect(mockUE.MicrophoneSDK.OnAudioLevelChanged).toHaveBeenCalledWith(0.5);
  });
  
  test('麦克风错误事件', async () => {
    await bridge._initSDK();
    
    // 模拟麦克风错误事件
    const errorMessage = 'Permission denied';
    document.dispatchEvent(new CustomEvent('microphoneError', { detail: { error: errorMessage } }));
    
    // 验证UE函数被调用
    expect(mockUE.MicrophoneSDK.OnMicrophoneError).toHaveBeenCalledWith(errorMessage);
  });
  
  test('处理UE对象不存在的情况', () => {
    // 移除UE对象
    delete global.UE;
    
    // 创建新的桥接实例
    const newBridge = new UE5Bridge();
    
    // 测试调用UE5函数不抛出错误
    expect(() => newBridge._callUE5('OnMicrophoneStatusChanged', 'active')).not.toThrow();
    
    // 清理
    newBridge.dispose();
  });
  
  test('处理初始化失败', async () => {
    // 模拟SDK初始化失败
    jest.spyOn(bridge._sdk, 'initialize').mockResolvedValue(false);
    
    const initResult = await bridge._initSDK();
    expect(initResult).toBe(false);
  });
  
  test('处理开始麦克风失败', async () => {
    // 模拟开始监听失败
    jest.spyOn(bridge._sdk, 'startListening').mockResolvedValue(false);
    
    const result = await bridge.startMicrophone();
    expect(result).toBe(false);
  });
  
  test('处理停止麦克风失败', async () => {
    // 模拟停止监听失败
    jest.spyOn(bridge._sdk, 'stopListening').mockResolvedValue(false);
    
    const result = await bridge.stopMicrophone();
    expect(result).toBe(false);
  });
  
  test('资源释放', () => {
    expect(() => bridge.dispose()).not.toThrow();
  });
}); 